package com.siyuan2;

import org.junit.Test;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.OrderComparator;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;

import java.io.IOException;
import java.util.Locale;
import java.util.Map;


/**
 * @className: Demo
 * @Description: TODO spring 功能使用
 * @author: wzq
 * @date: 2022/8/25 10:53
 */
public class Demo {

	/**
	 * 通过 BeanDefinition 注册对象
	 */
	@Test
	public void test1() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);

		AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
		beanDefinition.setBeanClass(User.class);
		beanDefinition.setScope("prototype");
		beanDefinition.setInitMethodName("init");
		beanDefinition.setLazyInit(true);
		context.registerBeanDefinition("user", beanDefinition);

		System.out.println(context.getBean("user"));
		System.out.println(context.getBean("user"));
		System.out.println(context.getBean("user"));
	}

	/**
	 * 通过 AnnotatedBeanDefinitionReader 读取对象，并注册bean对象
	 */
	@Test
	public void test2() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);

		AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(context);
		reader.registerBean(User.class);

		System.out.println(context.getBean("user"));
	}

	/**
	 * 通过 XmlBeanDefinitionReader 读取对象，并注册bean对象
	 */
	@Test
	public void test3() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);

		XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(context);
		reader.loadBeanDefinitions("spring.xml");

		System.out.println(context.getBean("user"));
	}

	/**
	 * 通过 ClassPathBeanDefinitionScanner 指定包扫描路径，并注册bean对象
	 */
	@Test
	public void test4() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		context.refresh();

		ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
		scanner.scan("com.siyuan2");

		System.out.println(context.getBean("user"));
	}

	/**
	 * 通过 DefaultListableBeanFactory 注册bean对象
	 */
	@Test
	public void test5() {
		DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
		AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getRawBeanDefinition();
		beanDefinition.setBeanClass(User.class);
		beanFactory.registerBeanDefinition("user",beanDefinition);

		System.out.println(beanFactory.getBean("user"));
	}

	/**
	 * MesageSource 国际化
	 */
	@Test
	public void test6() {
		ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
		// 指定语言版本
		System.out.println(context.getMessage("test", null, new Locale("en")));
	}

	/**
	 * 通过 ApplicationContext 加载资源
	 */
	@Test
	public void test7() throws IOException {
		ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
		Resource resource = context.getResource("file:/Users/wzq/IdeaProjects/spring-framework/spring-siyuan/src/main/java/com/siyuan2/User.java");

		System.out.println(resource.contentLength());
		System.out.println(resource.getFilename());
		// TODO 如何根据resource注册bean

		Resource resource1 = context.getResource("https://www.baidu.com");
		System.out.println(resource1.contentLength());
		System.out.println(resource1.getURL());

		Resource resource2 = context.getResource("classpath:spring.xml");
		System.out.println(resource2.contentLength());
		System.out.println(resource2.getFilename());

		Resource[] resources = context.getResources("classpath:com/siyuan1/spring/*.class");
		for (Resource resource3 : resources) {
			System.out.println(resource3.getFilename());

		}

	}

	/**
	 * 获取运行时环境
	 */
	@Test
	public void test8() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);

		Map<String, Object> systemEnvironment = context.getEnvironment().getSystemEnvironment();
		System.out.println(systemEnvironment);

		System.out.println("=====================");

		Map<String, Object> systemProperties = context.getEnvironment().getSystemProperties();
		System.out.println(systemProperties);

		System.out.println("=====================");

		MutablePropertySources propertySources = context.getEnvironment().getPropertySources();
		System.out.println(propertySources);

		System.out.println("=====================");

		System.out.println(context.getEnvironment().getProperty("NO_PROXY"));
		System.out.println(context.getEnvironment().getProperty("sun.jnu.encoding"));
		System.out.println(context.getEnvironment().getProperty("name"));

	}

	/**
	 * 事件的发布订阅
	 */
	@Test
	public void test9(){
		ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
		context.publishEvent("发布时间");
	}

	/**
	 * 类型的转换 PropertyEditor
	 */
	@Test
	public void test10(){
		// 常规使用
		StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();
		propertyEditor.setAsText("1");
		User user = (User) propertyEditor.getValue();
		System.out.println(user.toString());

		// spring 中使用
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
		UserService userService = (UserService) context.getBean("userService");
		userService.test();
	}

	/**
	 * 类型的转换 ConversionService
	 */
	@Test
	public void test11(){
		// 常规使用
		DefaultConversionService conversionService = new DefaultConversionService();
		conversionService.addConverter(new StringToUserConverter());
		User user = conversionService.convert("2", User.class);
		System.out.println(user);

		// spring 中使用
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
		UserService userService = (UserService) context.getBean("userService");
		userService.test();
	}

	/**
	 * 类型的转换 ConversionService
	 */
	@Test
	public void test12(){
		// 常规使用
		SimpleTypeConverter typeConverter = new SimpleTypeConverter();
		typeConverter.registerCustomEditor(User.class,new StringToUserPropertyEditor());
		User user = typeConverter.convertIfNecessary("siyuan3", User.class);

		System.out.println(user);
	}

	/**
	 * OrderComparator
	 * AnnotationAwareOrderComparator
	 */
	@Test
	public void test13(){
		A a = new A();
		B b = new B();
		OrderComparator orderComparator = new OrderComparator();
		System.out.println(orderComparator.compare(a, b));

		C c = new C();
		D d = new D();
		AnnotationAwareOrderComparator annotationAwareOrderComparator = new AnnotationAwareOrderComparator();
		System.out.println(annotationAwareOrderComparator.compare(c, d));
	}

	/**
	 * BeanPostProcessor
	 */
	@Test
	public void test14(){
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
		System.out.println(context.getBean("user"));
	}

	/**
	 * BeanFactoryPostProcessor
	 */
	@Test
	public void test15(){
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
	}

	/**
	 * userFactoryBean
	 */
	@Test
	public void test16(){
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
		System.out.println(context.getBean("userFactoryBean"));
		System.out.println(context.getBean("&userFactoryBean"));
	}


	/**
	 * BeanFactoryPostProcessor
	 */
	@Test
	public void test17(){
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
		System.out.println(context.getBean("orderService"));
		System.out.println(context.getBean("userService"));
	}

	/**
	 * BeanFactoryPostProcessor
	 */
	@Test
	public void test18() throws IOException {
		SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();
		MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.siyuan2.UserService");

		ClassMetadata classMetadata = metadataReader.getClassMetadata();
		System.out.println(classMetadata.getClassName());

		AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
		for (String annotationType : annotationMetadata.getAnnotationTypes()) {
			System.out.println(annotationType);
		}
	}




}
